home *** CD-ROM | disk | FTP | other *** search
Text File | 1995-11-08 | 14.9 KB | 489 lines | [TEXT/KAHL] |
- //------------------------- © 1991-1995 by James G. Stout --------------------------
- // File : cdefGBox.c
- // Date : September 1,1991
- // Author : Jim Stout
- // :
- // Purpose : "Group Box" CDEF
- // : A very simple CDEF that draws a titled box. It supports
- // : 3 variations - grayLine, ctl3D, insetBox, and useWindFont (1,2, 4 & 8)
- // :
- // : Pretty straight forward code here, only trick here is to use the
- // : contrlMax value as the height of the control. This is done to keep
- // : the Control Manager from thinking the control overlays the controls
- // : you want inside the GroupBox. Set the real control rect to some value
- // : sufficient to see the title in your resource editor and set contrlMax
- // : to the height of the box you want drawn.
- // :
- // ** IMPORTANT INFORMATION **
- // :
- // : Since the Control Manager doesn't know about the extra drawing done
- // : by this control, some extra handling is required for update events.
- // : Just calling UpdtControl() will not suffice since there could be a
- // : portion of this control that needs to be drawn that is outside the
- // : "official" control rect.
- // :
- // : So, make sure you call Draw1Control() in response to an update for
- // : any control that uses this CDEF. Calling DrawControls is ok too, but
- // : will draw all of the controls in the window.
- // :
- // : If you find a use for this, I'd love to know about it. Bug reports
- // : are always interesting.
- // :
- // : Internet : JimS@WRQ.COM(work hours, PST)
- // : AppleLink : WRQ (daily)
- // : CompuServe : 73240,2052 (weekly or so)
- // : AOL : JasG (weekly or so)
- // : eWorld : Jim Stout (weekly or so)
- //----------------------------------------------------------------------------------
- //#define _DEBUGCDEF
-
- #include "fatCDEF.h"
-
- #include <Controls.h>
- #include <LowMem.h>
- #include <Memory.h>
- #include <ToolUtils.h>
- #include <Types.h>
-
- #include "colorCDEF.h"
- #include "grayCDEF.h"
- #include "miscCDEF.h"
-
- #include "cdefGBox.h"
-
- #ifdef _DEBUGCDEF
- pascal long CDmain (short, ControlHandle, short, long);
-
- pascal long CDmain (short varCode, ControlHandle theCtl, short message, long param)
- #else
- //==================================================================================
- // CDEF entry point
- //==================================================================================
-
- pascal long main (short varCode, ControlHandle theCtl, short message, long param)
- #endif
- {
- gbDataHandle hGB;
- Rect r;
- GrafPtr thisPort;
- SignedByte cState, dState;
-
- #include "fatEntry.c"
-
- cState = HGetState((Handle)theCtl);
- HLock((Handle)theCtl);
- if((**theCtl).contrlData) {
- dState = HGetState((**theCtl).contrlData);
- HLock((**theCtl).contrlData);
- }
-
- switch(message) {
-
- case initCntl:
- hGB = (gbDataHandle)NewHandle(sizeof(gbData));
- if(hGB) {
- GetPort(&thisPort);
- (**hGB).realHt = (**theCtl).contrlMax; // true height of control
-
- r = (**hGB).titleRect = (**theCtl).contrlRect;// we'll adjust this later
- r.bottom = r.top + (**hGB).realHt+1; // for font size…
- r.right++; // allow for 3D shadow
-
- InvalRect(&r); // fool ControlMgr since
- // since we draw outside
- // the true controlRect.
-
- (**hGB).txFont = thisPort->txFont;
- (**hGB).txSize = thisPort->txSize;
-
- (**theCtl).contrlData = (Handle)hGB; // save our data
- if((**theCtl).contrlData) {
- dState = HGetState((**theCtl).contrlData);
- HLock((**theCtl).contrlData);
- }
- }
- break;
-
- case dispCntl:
- hGB = (gbDataHandle)(**theCtl).contrlData;
- if(hGB) {
- r = (**theCtl).contrlRect;
- r.bottom = r.top + (**hGB).realHt+1; // can't rely on Control Mgr
- r.right++; // to erase our "fake" rect
- EraseRect(&r); // or the 3D shadow.\
- HUnlock((Handle)hGB);
- DisposeHandle((Handle)hGB);
- (**theCtl).contrlData = 0;
- }
- break;
-
- case drawCntl:
- doDraw(theCtl, varCode);
- break;
-
- case calcCRgns:
- RectRgn((RgnHandle)(param & 0x7fffffffL), &(*theCtl)->contrlRect);
- break;
-
- case calcCntlRgn:
- case calcThumbRgn:
- RectRgn((RgnHandle)(param), &(*theCtl)->contrlRect);
- break;
- }
-
- if((**theCtl).contrlData)
- HSetState((**theCtl).contrlData, dState);
- HSetState((Handle)theCtl, cState);
-
- #include "fatExit.c"
-
- return (0L); // this control does nothing
- }
-
- //==================================================================================
- // If running with System 7, use DeviceLoop to gracefully handle multiple screens.
- // Simulate DeviceLoop if using System 6...
- //==================================================================================
-
- static void doDraw(ControlHandle theCtl, short varCode)
- {
- short txF, txS;
- GrafPtr thisPort;
- devLoopHandle hDl;
- Rect fullRect;
- RgnHandle saveClip, hRgn;
- gbDataHandle hGB;
- DeviceLoopDrawingUPP drawControlUPP;
-
- hGB = (gbDataHandle)(**theCtl).contrlData;
- if(!hGB)
- return; // oops!
-
- //----------------------------------------------------------------------------------
- // set window font & size info
- //----------------------------------------------------------------------------------
-
- GetPort(&thisPort);
-
- if(!(varCode & useWindFont)) { // use system font
- txF = thisPort->txFont; // save current
- txS = thisPort->txSize;
- TextFont(LMGetSysFontFam()); // set system as current
- TextSize(LMGetSysFontSize());
- }
-
- //----------------------------------------------------------------------------------
- // Create our data handle to pass to DeviceLoop
- //----------------------------------------------------------------------------------
-
- hDl = (devLoopHandle)NewHandle(sizeof(devLoopData));
- if(hDl) {
- drawControlUPP = NewDeviceLoopDrawingProc(drawControl);
-
- (**hDl).theCtl = theCtl;
- (**hDl).varCode = varCode;
-
- fullRect = (**theCtl).contrlRect;
- fullRect.bottom = fullRect.top + (**hGB).realHt +1;
- fullRect.right++;
- (**hDl).controlRect = fullRect;
-
- //----------------------------------------------------------------------------------
- // Do the clip region properly. Thanks Ari!
- //----------------------------------------------------------------------------------
-
- saveClip = NewRgn();
- GetClip(saveClip);
-
- hRgn = NewRgn();
- RectRgn(hRgn, &(**hDl).controlRect);
- SectRgn(saveClip, hRgn, hRgn);
-
- if(EmptyRgn(hRgn)) { // if empty, don't waste
- DisposeRgn(saveClip); // time drawing...
- DisposeRgn(hRgn);
- return;
- }
-
- //----------------------------------------------------------------------------------
- // Call DeviceLoop to take care of our drawing
- //----------------------------------------------------------------------------------
-
- if(getOSVers() >= 0x0700) {
- DeviceLoop (hRgn, drawControlUPP, (long)hDl, 0);
- }
- else {
- sys6DeviceLoop (hRgn, drawControlUPP, (long)hDl, 0);
- }
-
- SetClip(saveClip);
- DisposeRgn(hRgn);
- DisposeHandle((Handle)hDl);
- DisposeRoutineDescriptor(drawControlUPP);
- }
- //----------------------------------------------------------------------------------
- // restore window font & size info
- //----------------------------------------------------------------------------------
-
- if(!(varCode & useWindFont)) {
- TextFont(txF);
- TextSize(txS);
- }
- }
-
- //==================================================================================
- // as it says, the draw routine for the group box…
- //==================================================================================
- pascal void drawControl (short depth, short dFlags, GDHandle theDevice, long userData)
- {
-
- #pragma unused(dFlags, theDevice)
-
- ControlHandle theCtl;
- short varCode, boxType, titleWidth, titleHt;
- Rect titleRect, boxRect;
- RgnHandle rgSave, rgClip, rgTitle;
- GrafPtr thisPort;
- FontInfo f;
- PenState savePen;
- RGBColor saveFore,saveBack,grayColor;
- RGBColor rgbA = {0xAAAA, 0xAAAA, 0xAAAA};
- Boolean inColor = false, bgInColor = false, haveGray = false;
- gbDataHandle hGB;
- devLoopHandle hDl;
-
- //----------------------------------------------------------------------------------
- // Can we draw?
- //----------------------------------------------------------------------------------
-
- hDl = (devLoopHandle)userData; // need control & varCode
- if(hDl) {
- theCtl = (**hDl).theCtl;
- varCode = (**hDl).varCode;
- }
- else
- return;
-
- //----------------------------------------------------------------------------------
- // get our private data
- //----------------------------------------------------------------------------------
-
- hGB = (gbDataHandle)(**theCtl).contrlData;
- if(!hGB)
- return; // oops!
-
- HLock((Handle)hGB);
-
- (**hGB).titleRect = (**theCtl).contrlRect;
- (**hGB).realHt = (**theCtl).contrlMax; // true height of control
-
- //----------------------------------------------------------------------------------
- // setup our drawing environment
- //----------------------------------------------------------------------------------
-
- GetPort(&thisPort);
- GetPenState(&savePen);
- PenSize(1,1);
- PenPat( (ConstPatternParam) "\xff\xff\xff\xff\xff\xff\xff\xff");
-
- rgClip = NewRgn();
- rgTitle = NewRgn();
- rgSave = NewRgn();
- GetClip(rgSave);
-
- boxType = varCode;
-
- if(varCode & useWindFont)
- boxType ^= useWindFont;
-
- //----------------------------------------------------------------------------------
- // Clear the title box at the top so that any font changes don't leave junk
- // lying around.
- //----------------------------------------------------------------------------------
-
- if((thisPort->txFont != (**hGB).txFont) || // if font changed,
- (thisPort->txSize != (**hGB).txSize)) { // clear rect to erase
- (**hGB).txFont = thisPort->txFont; // old font
- (**hGB).txSize = thisPort->txSize;
- EraseRect(&(**hGB).titleRect); // clear previous rect
- }
-
- GetFontInfo(&f); // get font metrics
- titleRect = (**hGB).titleRect; // calc new title rect
- titleRect.bottom = titleRect.top +
- f.ascent + f.descent;
- (**hGB).titleRect = titleRect; // save new title rect
-
- f.ascent+=1; // fudge a bit so the
- titleRect.bottom = titleRect.top + 2*(f.ascent/2); // title lines up
- titleHt = titleRect.bottom-titleRect.top; // nicely…
-
- //----------------------------------------------------------------------------------
- // calculate the real rect for the control
- //----------------------------------------------------------------------------------
-
- boxRect = (**hGB).titleRect;
- boxRect.bottom = boxRect.top + (**hGB).realHt; // full control rect
- boxRect.top+=titleHt/2; // box halves title area
-
- //----------------------------------------------------------------------------------
- // do color checks
- //----------------------------------------------------------------------------------
-
- if(depth > 1 && !(((CGrafPtr)thisPort)->portVersion & 0x8000))
- depth = 1;
- if(depth > 2) { // yes…
- inColor = true;
- saveColors(&saveFore, &saveBack);
- setPartColor(theCtl, cFrameColor, true);
- if((**theCtl).contrlHilite == 0xFF) { // inactive control
- haveGray = getGray(&grayColor);
- }
- bgInColor = true;
- if(saveBack.red == 65535 && // is bg white?
- saveBack.green == 65535 &&
- saveBack.blue == 65535)
- bgInColor = false; // no 3D effects
- }
-
- //----------------------------------------------------------------------------------
- // Draw the control title
- //----------------------------------------------------------------------------------
- titleWidth = StringWidth((*theCtl)->contrlTitle) + 10;
-
- if(titleWidth > 10) { // i.e. we have a title
- titleRect.left += 10;
- titleRect.right = titleRect.left + titleWidth;
- if(inColor) {
- if(bgInColor && varCode & ctl3D) { // do 3D stuff
- ForeColor(whiteColor);
- MoveTo(titleRect.left + 6,boxRect.top+titleHt/2-f.leading+1);
- DrawString((*theCtl)->contrlTitle); // embossed title in white
- }
- setPartColor(theCtl, cTextColor, true); // get fgColor
-
- if(haveGray) { // must be inactive
- getGray(&grayColor); // grayed cTextColor
- RGBForeColor(&grayColor);
- }
- }
-
- MoveTo(titleRect.left + 5,boxRect.top+titleHt/2-f.leading);
- DrawString((*theCtl)->contrlTitle); // draw the title in fgColor
-
- //
- // watch carefully! To keep the frame from drawing through the title text, set
- // a clip region that excludes the title rect
- //
- RectRgn(rgTitle, &titleRect);
- DiffRgn(rgSave, rgTitle, rgClip);
- SetClip(rgClip);
- }
-
- //----------------------------------------------------------------------------------
- // draw the group box frame
- //----------------------------------------------------------------------------------
-
- if(varCode & grayLine) {
- PenPat( (ConstPatternParam) "\x55\xAA\x55\xAA\x55\xAA\x55\xAA");
- }
-
- switch(boxType) {
- case 2:
- case 3:
- if(inColor) {
- ForeColor(whiteColor);
- OffsetRect(&boxRect, 1, 1);
- FrameRect(&boxRect); // white shadow
- OffsetRect(&boxRect, -1, -1);
- RGBForeColor(&saveFore);
- FrameRect(&boxRect);
- }
- else
- FrameRect(&boxRect);
- break;
- case 5:
- case 7:
- PenPat( (ConstPatternParam) "\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF");
- if(inColor) {
- boxRect.left++;
- FrameRect(&boxRect);
- RGBForeColor(&rgbA); // slight 3D effect
- MoveTo(boxRect.left-1,boxRect.bottom);
- LineTo(boxRect.left-1,boxRect.top-1);
- LineTo(boxRect.right,boxRect.top-1);
- ForeColor(whiteColor);
- LineTo(boxRect.right, boxRect.bottom);
- LineTo(boxRect.left, boxRect.bottom);
- }
- else
- FrameRect(&boxRect);
- break;
- }
-
-
- if(inColor) {
- setPartColor(theCtl, cFrameColor, true); // groupBox color
-
- if((**theCtl).contrlHilite == 0xFF) { // inactive control
- haveGray = getGray(&grayColor);
- if(haveGray) // grayed cFrameColor
- RGBForeColor(&grayColor);
- }
- }
-
- switch(boxType) {
- case 0:
- case 1:
- case 2:
- case 5:
- case 7:
- FrameRect(&boxRect); // frame the groupbox
- break;
- case 4:
- case 6:
- if(bgInColor) {
- ForeColor(whiteColor);
- MoveTo(boxRect.right, boxRect.top);
- LineTo(boxRect.right, boxRect.bottom);
- LineTo(boxRect.left, boxRect.bottom);
- setPartColor(theCtl, cFrameColor, true);
- getGray(&grayColor);
- RGBForeColor(&grayColor);
- LineTo(boxRect.left, boxRect.top);
- LineTo(boxRect.right, boxRect.top);
- }
- else
- FrameRect(&boxRect);
- break;
- }
-
- SetClip(rgSave);
- DisposeRgn(rgSave);
- DisposeRgn(rgClip);
- DisposeRgn(rgTitle);
-
- //----------------------------------------------------------------------------------
- // gray out the old, System 6 way if we didn't get a gray color
- //----------------------------------------------------------------------------------
-
- if(!haveGray && (**theCtl).contrlHilite == 0xFF) { // no gray but inactive
-
- PenPat( (ConstPatternParam) "\xAA\x55\xAA\x55\xAA\x55\xAA\x55");
- PenMode(patBic);
- FrameRect(&boxRect); // gray the groupbox
- PaintRect(&(**hGB).titleRect); // gray the title
- }
-
- //----------------------------------------------------------------------------------
- // restore drawing environment
- //----------------------------------------------------------------------------------
-
- if(inColor) {
- restoreColors(&saveFore, &saveBack);
- }
-
- SetPenState(&savePen);
-
- HUnlock((Handle)hGB);
- }